//********************************************************************
//
//				LCD_driver.c: Interface for Nokia LCD
//
//********************************************************************
#include "display/spi_lcd.h"
#include "system.h"

//********************************************************************
//
//				Global Variables for LCD driver
//
//********************************************************************
//Usage: spilcd_ClearScreen(black);
//Inputs: char color: 8-bit color to be sent to the screen.
//Outputs: None
//Description: This function will clear the screen with "color" by writing the
//			   color to each location in the RAM of the LCD.
void spilcd_ClearScreen(int color) {
	int i;
#ifdef EPSON
	spilcd_SendCommand(PASET);
	spilcd_SendData(0);
	spilcd_SendData(131);

	spilcd_SendCommand(CASET);
	spilcd_SendData(0);
	spilcd_SendData(131);

	spilcd_SendCommand(RAMWR);
#endif
#ifdef	PHILLIPS
	spilcd_SendCommand(PASETP);
	spilcd_SendData(0);
	spilcd_SendData(132); //131

	spilcd_SendCommand(CASETP);
	spilcd_SendData(0);
	spilcd_SendData(132);

	spilcd_SendCommand(RAMWRP);
#endif

#ifdef LCD_COLOR_DEPTH_12
	for(i=0; i < (132*132)/2; i++) {
		spilcd_SendData((unsigned char)(color>>4)&0x00FF);
		spilcd_SendData((unsigned char)((color&0x0F)<<4)|((color>>8) & 0x0F));
		spilcd_SendData((unsigned char)(color&0x0FF));
	}
#endif

#ifdef LCD_COLOR_DEPTH_16
	for(i=0; i < 17424; i++) {
		spilcd_SendData((unsigned char)(color>>8));
		spilcd_SendData((unsigned char)(color & 0x00FF));
	}
#endif
}

//Usage: spilcd_SendCommand(data);
//Inputs: char data - character command to be sent to the LCD
//Outputs: None
//Description: Sends a 9 bit command over SPI to the LCD with
//			   the first bit HIGH indicating "command" mode.
void inline spilcd_SendCommand(unsigned char data) {
	spi_LCDSend(1,data);
}

//Usage: spilcd_SendData(data);
//Inputs: char data - character data to be sent to the LCD
//Outputs: None
//Description: Sends a 9 bit command over SPI to the LCD with
//			   the first bit LOW indicating "data" mode.
void inline spilcd_SendData(unsigned char data) {
	spi_LCDSend(0,data);
}

void spilcd_InitPhillips12Bits() {
	spilcd_SendCommand(SLEEPOUT);
	spilcd_SendCommand(MADCTL);
	// Line address bottom to top - connector on top-right
	// x increases from left to right
	// y increases from top to bottom
	spilcd_SendData(32);
	spilcd_SendCommand(SETCON);
	spilcd_SendData(0x30);
	spilcd_SendCommand(BSTRON);
	spilcd_SendCommand(COLMOD);
	spilcd_SendData(0x3);	// 12 bits!
	spilcd_SendCommand(NOPP);
	delay_ms(200);
	spilcd_SendCommand(DISPON);
}

void spilcd_InitPhillips16Bits() {
	spilcd_SendCommand(SLEEPOUT);
	//spilcd_SendCommand(INVON);
	spilcd_SendCommand(COLMOD);

	spilcd_SendData(0x5);	// 16 bits!
	spilcd_SendCommand(MADCTL);
	// Line address bottom to top - connector on top-right
	// x increases from left to right
	// y increases from top to bottom
	spilcd_SendData(32);

	spilcd_SendCommand(SETCON);
	spilcd_SendData(0x40);


	spilcd_SendCommand(NOPP);
	delay_ms(200);
	spilcd_SendCommand(DISPON);
}

//Usage: spilcd_Init();
//Inputs: None
//Outputs: None
//Description:  Initializes the LCD regardless of if the controlller is an EPSON or PHILLIPS.
void spilcd_Init(void) {
	int j;

	delay_ms(200);

	// reset is always done using software SPI
	#ifdef USE_SOFT_SPI_FOR_LCD
		spi_LCDSoftwareInit();
	#endif
	#ifdef USE_HARD_SPI_FOR_LCD
		// change to hardware port
		spi_LCDHardwareInit(8);
	#endif

	LCD_CLR = (LCD_SCK | LCD_MOSI); //output_low (SPI_CLK);//output_low (SPI_DO);
	LCD_SET = LCD_CS; //output_high (LCD_CS);
	for (j = 0; j < 16; j++)
		asm volatile ("nop");
	LCD_CLR = LCD_RESET; //output_low (LCD_RESET);
	for (j = 0; j < 300000; j++)
		asm volatile ("nop");
	LCD_SET = LCD_RESET; //output_high (LCD_RESET);
	LCD_SET = (LCD_SCK | LCD_MOSI);
	for (j = 0; j < 300000; j++)
		asm volatile ("nop");


#ifdef PHILLIPS

#ifdef LCD_COLOR_DEPTH_16
	spilcd_InitPhillips16Bits();
#endif
#ifdef LCD_COLOR_DEPTH_12
	spilcd_InitPhillips12Bits();
#endif

#endif

}

//Usage: spilce_PutPixel(white, 0, 0);
//Inputs: unsigned char color - desired color of the pixel
//		  unsigned char x - Page address of pixel to be colored
//		  unsigned char y - column address of pixel to be colored
//Outputs: None
//Description: Sets the starting page(row) and column (x & y) coordinates in ram,
//  		   then writes the colour to display memory.  The ending x & y are left
//  		   maxed out so one can continue sending colour data bytes to the 'open'
//  		   RAMWR command to fill further memory.  issuing any red command
//  		   finishes RAMWR.
void spilcd_PutPixel(unsigned int color, unsigned int x, unsigned int y) {
	unsigned char aux1,aux2;
#ifdef EPSON
	spilcd_SendCommand(PASET); // page start/end ram
	spilcd_SendData(x);
	spilcd_SendData(x);

	spilcd_SendCommand(CASET); // column start/end ram
	spilcd_SendData(y);
	spilcd_SendData(y);

	spilcd_SendCommand(RAMWR); // write

	#ifdef LCD_COLOR_DEPTH_12

	//TODO: Revisar que duplica puntos!

	spilcd_SendData((color >> 4) & 0x00FF);
	spilcd_SendData(((color & 0x0F) << 4) | (color >> 8));
	spilcd_SendData(color & 0x0FF); // nop(EPSON)

	#elif LCD_COLOR_DEPTH_16

	#endif

#endif
#ifdef	PHILLIPS
	spilcd_SendCommand(PASETP); // page start/end ram
	spilcd_SendData(x);
	spilcd_SendData(x);

	spilcd_SendCommand(CASETP); // column start/end ram
	spilcd_SendData(y);
	spilcd_SendData(y);

	spilcd_SendCommand(RAMWRP); // write

	#ifdef LCD_COLOR_DEPTH_12
/*
	spilcd_SendData((unsigned char)((color>>4)&0x00FF));
	spilcd_SendData((unsigned char)(((color&0x0F)<<4)|0x00));
	*/
	aux1 = ((color >> 4) & 0xFFFF);
	aux2 = (((color & 0x0F) << 4) | 0x00);

	spilcd_SendData((unsigned char)aux1);
	spilcd_SendData((unsigned char)aux2);
	spilcd_SendCommand(NOPP);

	#endif
	#ifdef LCD_COLOR_DEPTH_16

	aux1 = ((color >> 8) & 0x00FF);
	aux2 = (color & 0x00FF);

	spilcd_SendData((unsigned char)aux1);
	spilcd_SendData((unsigned char)aux2);


	//spilcd_SendData((unsigned char)(color>>8);
	//spilcd_SendData((unsigned char)(color & 0x00FF));

	#endif
#endif

}

